package com.getpebble.android.framework;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build.VERSION;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Messenger;
import android.support.v4.app.NotificationCompat.Builder;
import com.getpebble.android.PebbleApplication;
import com.getpebble.android.R;
import com.getpebble.android.bluetooth.device.AbsDeviceService;
import com.getpebble.android.bluetooth.device.ConnectionResult;
import com.getpebble.android.bluetooth.device.IRemoteDeviceCallback;
import com.getpebble.android.bluetooth.device.RemoteDevice;
import com.getpebble.android.bluetooth.device.RemoteDeviceMetaData;
import com.getpebble.android.bluetooth.protocol.ProtocolMessage;
import com.getpebble.android.bluetooth.radio.PebbleBluetoothAdapter;
import com.getpebble.android.common.core.trace.Trace;
import com.getpebble.android.common.framework.ReadOnlyPreferences;
import com.getpebble.android.common.model.ConnectionStatus;
import com.getpebble.android.common.model.PblDevice;
import com.getpebble.android.common.model.PblDeviceModel.PblDeviceRecord;
import com.getpebble.android.common.util.DiscoveryUtils;
import com.getpebble.android.common.util.FileUtil;
import com.getpebble.android.framework.DeviceInterfaces.IAdapterQuery;
import com.getpebble.android.framework.DeviceInterfaces.IAdapterQueryCallback;
import com.getpebble.android.framework.DeviceInterfaces.IDeviceConnector;
import com.getpebble.android.framework.DeviceInterfaces.IDeviceConnectorCallback;
import com.getpebble.android.framework.DeviceInterfaces.IDeviceFetcher;
import com.getpebble.android.framework.DeviceInterfaces.IDeviceFetcherCallback;
import com.getpebble.android.framework.DeviceInterfaces.IDeviceMessageReceivedCallback;
import com.getpebble.android.framework.DeviceInterfaces.IDeviceMessageSender;
import com.getpebble.android.framework.DeviceInterfaces.IDeviceMessageSentCallback;
import com.getpebble.android.framework.developer.PblDeviceObserver.ConnectedDeviceChangeListener;
import com.getpebble.android.main.activity.MainActivity;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class PblFrameworkService extends AbsDeviceService implements IAdapterQuery, IDeviceConnector, IDeviceFetcher, IDeviceMessageSender {
    public static final String TAG = PblFrameworkService.class.getSimpleName();
    private Set<IAdapterQueryCallback> mBtAdapterCallbacks = new HashSet();
    private Set<IDeviceConnectorCallback> mBtConnectionCallbacks = new HashSet();
    private Set<IDeviceFetcherCallback> mBtDeviceCallbacks = new HashSet();
    private Set<IDeviceMessageReceivedCallback> mBtMessageReceivedCallbacks = new HashSet();
    private Set<IDeviceMessageSentCallback> mBtMessageSentCallbacks = new HashSet();
    private ConnectedDeviceChangeListener mConnectedDeviceChangeListener = new ConnectedDeviceChangeListener() {
        public void notifyConnectedDeviceChanged() {
            Trace.debug(PblFrameworkService.TAG, "PebbleObserver onChange()");
            PblDeviceRecord lastConnectedDevice = PebbleApplication.getLastConnectedDeviceRecord();
            if (lastConnectedDevice == null) {
                PblFrameworkService.this.showNotConnectedNotification();
            } else if (lastConnectedDevice.connectionStatus.equals(ConnectionStatus.CONNECTED)) {
                PblFrameworkService.this.showConnectedNotification();
            } else if (lastConnectedDevice.connectionStatus.equals(ConnectionStatus.CONNECTING)) {
                PblFrameworkService.this.showConnectingNotification();
            } else {
                PblFrameworkService.this.showNotConnectedNotification();
            }
        }
    };
    private NotificationType mCurrentNotificationType = NotificationType.NONE;
    private PblFrameworkManager mFrameworkManager;
    private HandlerThread mHandlerThread;
    private Messenger mMessenger;
    private Map<PblDevice, RemoteDevice> mRemoteDevices = new HashMap();

    private enum NotificationType {
        NONE,
        CONNECTING,
        CONNECTED,
        NOT_CONNECTED
    }

    private class PblRemoteDevice extends RemoteDevice {
        private PblRemoteDevice(PblDevice device, IRemoteDeviceCallback callback) {
            super(device.getAddress(), callback);
        }
    }

    public void onCreate() {
        Trace.debug(TAG, "onCreate()");
        super.onCreate();
        FileUtil.purgeTemporaryFiles(getApplicationContext());
        showNotConnectedNotification();
        this.mHandlerThread = new HandlerThread(PblFrameworkService.class.getSimpleName());
        this.mHandlerThread.start();
        try {
            this.mFrameworkManager = PblFrameworkManager.create(getApplicationContext(), this, this, this, this);
            this.mMessenger = new Messenger(this.mFrameworkManager.getIncomingMessageHandlerWithLooper(this.mHandlerThread.getLooper()));
            PebbleApplication.addConnectedDeviceChangeListener(this.mConnectedDeviceChangeListener);
        } catch (IllegalArgumentException e) {
            Trace.error(TAG, "Failed to create framework", e);
            stopSelf();
        } catch (IllegalStateException e2) {
            Trace.error(TAG, "Failed to create framework", e2);
            stopSelf();
        }
    }

    public void onDestroy() {
        Trace.debug(TAG, "onDestroy()");
        super.onDestroy();
        this.mHandlerThread.quit();
        this.mHandlerThread = null;
        this.mFrameworkManager.destroy();
        this.mFrameworkManager = null;
        this.mMessenger = null;
        this.mBtAdapterCallbacks.clear();
        this.mBtMessageReceivedCallbacks.clear();
        this.mBtMessageSentCallbacks.clear();
        this.mBtDeviceCallbacks.clear();
        this.mBtConnectionCallbacks.clear();
        for (RemoteDevice device : this.mRemoteDevices.values()) {
            disconnectFromDevice(device);
        }
        this.mRemoteDevices.clear();
        PebbleApplication.removeConnectedDeviceChangeListener(this.mConnectedDeviceChangeListener);
    }

    public SharedPreferences getSharedPreferences(String name, int mode) {
        return new ReadOnlyPreferences(this, name);
    }

    private RemoteDevice getRemoteDevice(PblDevice device) {
        if (!this.mRemoteDevices.containsKey(device)) {
            this.mRemoteDevices.put(device, new PblRemoteDevice(device, this));
        }
        return (RemoteDevice) this.mRemoteDevices.get(device);
    }

    public IBinder onBind(Intent intent) {
        Messenger messenger = this.mMessenger;
        if (messenger == null) {
            return null;
        }
        return messenger.getBinder();
    }

    protected void onRemoteDeviceConnectionResult(RemoteDeviceMetaData deviceMetaData, ConnectionResult result) {
        PblDevice device = new PblDevice(deviceMetaData.getName(), deviceMetaData.getMacAddress());
        for (IDeviceConnectorCallback callback : this.mBtConnectionCallbacks) {
            callback.onDeviceConnectionResult(device, result);
        }
    }

    protected void onRemoteDeviceDisconnectSuccess(RemoteDeviceMetaData deviceMetaData) {
        PblDevice device = new PblDevice(deviceMetaData.getName(), deviceMetaData.getMacAddress());
        for (IDeviceConnectorCallback callback : this.mBtConnectionCallbacks) {
            callback.onDeviceDisconnected(device);
        }
    }

    protected void onRemoteDeviceBonded(RemoteDeviceMetaData deviceMetaData) {
        PblDevice device = new PblDevice(deviceMetaData.getName(), deviceMetaData.getMacAddress());
        for (IDeviceFetcherCallback callback : this.mBtDeviceCallbacks) {
            callback.onDeviceBonded(device);
        }
    }

    protected void onRemoteDeviceUnbonded(RemoteDeviceMetaData deviceMetaData) {
        PblDevice device = new PblDevice(deviceMetaData.getName(), deviceMetaData.getMacAddress());
        for (IDeviceFetcherCallback callback : this.mBtDeviceCallbacks) {
            callback.onDeviceUnbonded(device);
        }
    }

    protected void onDiscoveryStarted() {
        this.mFrameworkManager.getState().setDiscoveryInProgress(true);
    }

    protected void onDiscoveryStopped() {
        this.mFrameworkManager.getState().setDiscoveryInProgress(false);
    }

    protected void onDeviceFound(RemoteDeviceMetaData deviceMetaData) {
        String address = deviceMetaData.getMacAddress();
        if (DiscoveryUtils.isPebbleDevice(address, deviceMetaData.getBluetoothClass())) {
            String name = DiscoveryUtils.getPebbleDisplayName(deviceMetaData.getName(), address, this);
            if (name != null) {
                PblDevice device = new PblDevice(name, address, deviceMetaData.getRssi());
                for (IDeviceFetcherCallback callback : this.mBtDeviceCallbacks) {
                    callback.onDeviceDiscovered(device);
                }
            }
        }
    }

    protected void onRemoteDeviceDataSendSuccess(RemoteDeviceMetaData deviceMetaData) {
        PblDevice device = new PblDevice(deviceMetaData.getName(), deviceMetaData.getMacAddress());
        for (IDeviceMessageReceivedCallback callback : new HashSet(this.mBtMessageReceivedCallbacks)) {
            callback.onMessageSendSuccess(device);
        }
    }

    protected void onRemoteDeviceDataSendFailed(RemoteDeviceMetaData deviceMetaData) {
        PblDevice device = new PblDevice(deviceMetaData.getName(), deviceMetaData.getMacAddress());
        for (IDeviceMessageReceivedCallback callback : new HashSet(this.mBtMessageReceivedCallbacks)) {
            callback.onMessageSendFailed(device);
        }
    }

    protected void onRemoteDeviceDataReceived(RemoteDeviceMetaData deviceMetaData, ProtocolMessage message) {
        PblDevice device = new PblDevice(deviceMetaData.getName(), deviceMetaData.getMacAddress());
        for (IDeviceMessageReceivedCallback callback : new HashSet(this.mBtMessageReceivedCallbacks)) {
            callback.onDeviceMessageReceived(device, message);
        }
    }

    protected synchronized void onAdapterEnabled() {
        Trace.debug(TAG, "onAdapterEnabled");
        for (IAdapterQueryCallback callback : this.mBtAdapterCallbacks) {
            callback.onAdapterStateChanged(true);
        }
    }

    protected synchronized void onAdapterDisabled() {
        Trace.debug(TAG, "onAdapterDisabled");
        for (IAdapterQueryCallback callback : this.mBtAdapterCallbacks) {
            callback.onAdapterStateChanged(false);
        }
    }

    protected synchronized void onAdapterError() {
        Trace.debug(TAG, "onAdapterError");
        for (IAdapterQueryCallback callback : this.mBtAdapterCallbacks) {
            callback.onAdapterError();
        }
    }

    public boolean isDiscovering() {
        PebbleBluetoothAdapter adapter = AbsDeviceService.getPebbleBluetoothAdapter();
        if (adapter == null) {
            return false;
        }
        return adapter.isDiscovering();
    }

    public boolean startDiscovery() {
        return super.startDiscovery();
    }

    public boolean cancelDiscovery() {
        return super.cancelDiscovery();
    }

    public boolean getAdapterEnabled() {
        PebbleBluetoothAdapter adapter = AbsDeviceService.getPebbleBluetoothAdapter();
        if (adapter != null) {
            return adapter.isEnabled();
        }
        Trace.warning(TAG, "getAdapterEnabled: adapter is null");
        return false;
    }

    public synchronized void registerBluetoothAdapterCallback(IAdapterQueryCallback callback) {
        this.mBtAdapterCallbacks.add(callback);
    }

    public synchronized void unregisterBluetoothAdapterCallback(IAdapterQueryCallback callback) {
        this.mBtAdapterCallbacks.remove(callback);
    }

    public Set<PblDevice> getBondedPblDevices() {
        Trace.debug(TAG, "getBondedPblDevices()");
        HashSet<PblDevice> devices = new HashSet();
        Set<RemoteDeviceMetaData> devicesMeta = super.getBondedDevices();
        if (devicesMeta != null) {
            for (RemoteDeviceMetaData deviceMeta : devicesMeta) {
                String address = deviceMeta.getMacAddress();
                if (DiscoveryUtils.isPebbleDevice(address, deviceMeta.getBluetoothClass())) {
                    String name = DiscoveryUtils.getPebbleDisplayName(deviceMeta.getName(), address, this);
                    if (name != null) {
                        devices.add(new PblDevice(name, deviceMeta.getMacAddress(), deviceMeta.getRssi()));
                    }
                }
            }
        }
        return devices;
    }

    public synchronized void registerBluetoothDevicesCallback(IDeviceFetcherCallback callback) {
        this.mBtDeviceCallbacks.add(callback);
    }

    public synchronized void unregisterBluetoothDevicesCallback(IDeviceFetcherCallback callback) {
        this.mBtDeviceCallbacks.remove(callback);
    }

    public boolean connectToDevice(PblDevice device) throws IllegalArgumentException {
        return super.connectToDevice(getRemoteDevice(device));
    }

    public boolean disconnectFromDevice(PblDevice device) {
        return super.disconnectFromDevice(getRemoteDevice(device));
    }

    public void registerBluetoothConnectionCallback(IDeviceConnectorCallback callback) {
        this.mBtConnectionCallbacks.add(callback);
    }

    public void unregisterBluetoothConnectionCallback(IDeviceConnectorCallback callback) {
        this.mBtConnectionCallbacks.remove(callback);
    }

    public boolean sendMessage(PblDevice device, ProtocolMessage message) {
        boolean result = super.sendMessage(getRemoteDevice(device), message);
        for (IDeviceMessageSentCallback callback : this.mBtMessageSentCallbacks) {
            callback.onDeviceMessageSent(device, message);
        }
        return result;
    }

    public void registerBluetoothMessageCallback(IDeviceMessageReceivedCallback callback) {
        this.mBtMessageReceivedCallbacks.add(callback);
    }

    public void unregisterBluetoothMessageCallback(IDeviceMessageReceivedCallback callback) {
        this.mBtMessageReceivedCallbacks.remove(callback);
    }

    public void registerMessageSentCallback(IDeviceMessageSentCallback callback) {
        this.mBtMessageSentCallbacks.add(callback);
    }

    public void unregisterMessageSentCallback(IDeviceMessageSentCallback callback) {
        this.mBtMessageSentCallbacks.remove(callback);
    }

    @SuppressLint({"NewApi"})
    private void showNotification(String message, int icon, boolean isHidden) {
        if (getPackageManager() == null) {
            Trace.error(TAG, "showNotification() PackageManager is null");
            return;
        }
        Notification n = new Builder(this).setContentTitle(getString(R.string.pebble)).setContentText(message).setSmallIcon(icon).setAutoCancel(false).setOngoing(true).setOnlyAlertOnce(true).setContentIntent(PendingIntent.getActivity(this, 1, new Intent(getApplicationContext(), MainActivity.class), 134217728)).build();
        if (isHidden && VERSION.SDK_INT >= 16) {
            n.priority = -2;
        }
        startForeground(4244, n);
    }

    private synchronized void showConnectingNotification() {
        if (!NotificationType.CONNECTING.equals(this.mCurrentNotificationType)) {
            Trace.verbose(TAG, "Showing connecting notification");
            showNotification(getString(R.string.connecting_to_pebble), R.drawable.disconnected_notification, true);
            this.mCurrentNotificationType = NotificationType.CONNECTING;
        }
    }

    private synchronized void showConnectedNotification() {
        if (!NotificationType.CONNECTED.equals(this.mCurrentNotificationType)) {
            Trace.verbose(TAG, "Showing connected notification");
            showNotification(getString(R.string.your_pebble_is_connected), R.drawable.connected_status_bar, true);
            this.mCurrentNotificationType = NotificationType.CONNECTED;
        }
    }

    private synchronized void showNotConnectedNotification() {
        if (!NotificationType.NOT_CONNECTED.equals(this.mCurrentNotificationType)) {
            Trace.verbose(TAG, "Showing disconnected notification");
            showNotification(getString(R.string.no_pebble_connected), R.drawable.disconnected_notification, true);
            this.mCurrentNotificationType = NotificationType.NOT_CONNECTED;
        }
    }
}
